package com.whfp.coky.ui.base

import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.content.res.Resources
import android.os.Bundle
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import com.gyf.immersionbar.ImmersionBar
import com.hjq.bar.TitleBar
import com.hjq.demo.action.ToastAction
import com.whfp.coky.R
import com.whfp.coky.action.*
import com.whfp.coky.api.error.ErrorResult
import com.whfp.coky.databinding.ActivityRfidBinding
import com.whfp.coky.event.EventCode
import com.whfp.coky.event.EventMessage
import com.whfp.coky.ui.dialog.WaitDialog
import com.whfp.coky.ui.task.model.CheckDeviceBean
import com.whfp.coky.utils.GenericParadigmUtil
import com.whfp.coky.utils.LogUtil
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import java.lang.reflect.Method

/**
*
* 集成所有基类该有的功能
 * ToastAction：直接可以使用toast.show(),使用application，无需context；
 * TitleBarAction：界面中存在titlebar时，自动获取并可使用一系列titlebar的方法
 * ActivityAction：本地act和congtext获取，以及基本的跳转，startact4result可由eventbus代替
 * ClickAction：和软键盘有关？？暂时未知
 * HandlerAction：内部消息传递使用？？；
 * KeyboardAction：键盘？？；
 *
 *
 *
 *
 *
* author coky
* created 2022/2/21 17:44
*/

abstract class BaseActivity<VM : BaseViewModel<VB>, VB : ViewBinding> : AppCompatActivity(),
    ToastAction, TitleBarAction, ActivityAction,ClickAction, HandlerAction, BundleAction, KeyboardAction {

    /** 加载对话框 */
    private var dialog: BaseDialog? = null

    /** 对话框数量 */
    private var dialogCount: Int = 0

    /** 状态栏沉浸 */
    private var immersionBar: ImmersionBar? = null

    /** 标题栏对象 */
    private var titleBar: TitleBar? = null

    lateinit var vModel: VM
    lateinit var vBinding: VB


//----------------------------------------lifecycle-----------------------------------------------
    @Suppress("UNCHECKED_CAST")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initResources()
        var pathfinders = ArrayList<GenericParadigmUtil.Pathfinder>()
        pathfinders.add(GenericParadigmUtil.Pathfinder(0, 0))
        val clazzVM = GenericParadigmUtil.parseGenericParadigm(javaClass, pathfinders) as Class<VM>
        vModel = ViewModelProvider(this).get(clazzVM)

        pathfinders = ArrayList()
        pathfinders.add(GenericParadigmUtil.Pathfinder(0, 1))
        val clazzVB = GenericParadigmUtil.parseGenericParadigm(javaClass, pathfinders)
        var method = clazzVB?.getMethod("inflate", LayoutInflater::class.java)
        if (method == null){
            method = rebuildMethod()
        }
        vBinding = method.invoke(null, layoutInflater) as VB
        vModel.binding(vBinding)
        vModel.observe(this, this)

        setContentView(vBinding.root)
        initObserver()
        //初始化titlebar
        val titleBar = getTitleBar()
        titleBar?.setOnTitleBarListener(this)

        // 初始化沉浸式状态栏
        if (isStatusBarEnabled()) {
            getStatusBarConfig().init()
            // 设置标题栏沉浸
            if (titleBar != null) {
                ImmersionBar.setTitleBar(this, titleBar)
            }
        }

        initView()
        initData()
        LogUtil.e(getClassName())
    }

    open fun rebuildMethod(): Method {
//        基类实现界面时，需要手动反射,默认rfid
       return  ActivityRfidBinding::class.java.getMethod("inflate", LayoutInflater::class.java)
    }

    override fun onDestroy() {
        super.onDestroy()
        EventBus.getDefault().unregister(this)
        removeCallbacks()
        if (isShowDialog()) {
            hideDialog()
        }
        dialog = null
    }

    /**
     * 防止系统字体影响到app的字体
     * MVVM
     * @return
     */
    open fun initResources(): Resources? {
        val res: Resources = super.getResources()
        val config = Configuration()
        config.setToDefaults()
        res.updateConfiguration(config, res.displayMetrics)
        return res
    }

    private fun initObserver() {
        EventBus.getDefault().register(this)
        //loading
        (vModel as BaseViewModel<*>).isShowLoading.observe(this, Observer {
            if (it) showDialog() else hideDialog()
        })
        //错误信息
        (vModel as BaseViewModel<*>).errorData.observe(this, Observer {
            if (it.show) toast(it.errMsg)
            errorResult(it)
        })
//        设备校验
        (vModel as BaseViewModel<*>).checkedDevLD.observe(this, Observer {
           handleDevice(it)
        })
    }

    abstract fun initView()
    abstract fun initData()


//----------------------------------------base function------------------------------------------
    /**
     * 和 setContentView 对应的方法
     */
    open fun getContentView(): ViewGroup? {
        if (vBinding.root is ViewGroup){
            return  vBinding.root as ViewGroup
        }else{
            return null
        }
    }

    override fun getContext(): Context {
        return this
    }

    open fun getClassName(): String {
        val className = "BaseActivity"
        try {
            return javaClass.name
        } catch (e: Exception) {
        }
        return className
    }

    override fun finish() {
        super.finish()
        // 隐藏软键，避免内存泄漏
        hideKeyboard(currentFocus)
        overridePendingTransition(R.anim.left_in_activity, R.anim.left_out_activity)
    }

    /**
     * 如果当前的 Activity（singleTop 启动模式） 被复用时会回调
     */
    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        // 设置为当前的 Intent，避免 Activity 被杀死后重启 Intent 还是最原先的那个
        setIntent(intent)
    }


//----------------------------------------callback ----------------------------------------------
    /**
     * 事件传递
     */
    @Subscribe
    fun onEventMainThread(msg: EventMessage) {
        handleEvent(msg)
    }

    /**
     * 消息、事件接收回调
     */
    open fun handleEvent(msg: EventMessage) {
        LogUtil.e("handleEvent..code:${msg.code}..msg:${msg.msg}")
        if (msg.code == EventCode.LOGIN_OUT) {
            finish()
        }
    }

    /**
     * 接口请求错误回调
     */
    open fun errorResult(errorResult: ErrorResult) {}

    /**
     * 处理http验证过的设备
     */
    open fun handleDevice(bean: CheckDeviceBean){}


//----------------------------------------titlebar------------------------------------------------
    /**
     * 设置标题栏的标题
     */
    override fun setTitle(@StringRes id: Int) {
        title = getString(id)
    }

    /**
     * 设置标题栏的标题
     */
    override fun setTitle(title: CharSequence?) {
        super<AppCompatActivity>.setTitle(title)
        getTitleBar()?.title = title
    }

    override fun getTitleBar(): TitleBar? {
        if (titleBar == null) {
            titleBar = obtainTitleBar(getContentView())
        }
        return titleBar
    }

    override fun onLeftClick(view: View) {
        onBackPressed()
    }


//----------------------------------------dialog--------------------------------------------------
    /**
     * 当前加载对话框是否在显示中
     */
    open fun isShowDialog(): Boolean {
        return dialog != null && dialog!!.isShowing
    }

    /**
     * 显示加载对话框
     */
    open fun showDialog(str:String = "加载中..") {
        if (isFinishing || isDestroyed) {
            return
        }
        dialogCount++
        postDelayed(Runnable {
            if ((dialogCount <= 0) || isFinishing || isDestroyed) {
                return@Runnable
            }
            if (dialog == null) {
                dialog = WaitDialog.Builder(this)
                    .setCancelable(false)
                    .setMessage(str)
                    .create()
            }
            if (!dialog!!.isShowing) {
                dialog!!.show()
            }
        }, 300)
    }






    /**
     * 隐藏加载对话框
     */
    open fun hideDialog() {
        if (isFinishing || isDestroyed) {
            return
        }
        if (dialogCount > 0) {
            dialogCount--
        }
        if ((dialogCount != 0) || (dialog == null) || !dialog!!.isShowing) {
            return
        }
        dialog?.dismiss()
    }


//--------------------------------沉浸式状态栏ImmersionBar---------------------------------------
    /**
     * 是否使用沉浸式状态栏
     */
    protected open fun isStatusBarEnabled(): Boolean {
        return true
    }

    /**
     * 状态栏字体深色模式
     */
    open fun isStatusBarDarkFont(): Boolean {
        return true
    }

    /**
     * 获取状态栏沉浸的配置对象
     */
    open fun getStatusBarConfig(): ImmersionBar {
        if (immersionBar == null) {
            immersionBar = createStatusBarConfig()
        }
        return immersionBar!!
    }

    /**
     * 初始化沉浸式状态栏
     */
    protected open fun createStatusBarConfig(): ImmersionBar {
        return ImmersionBar.with(this) // 默认状态栏字体颜色为黑色
            .statusBarDarkFont(isStatusBarDarkFont()) // 指定导航栏背景颜色
            .navigationBarColor(R.color.white) // 状态栏字体和导航栏内容自动变色，必须指定状态栏颜色和导航栏颜色才可以自动变色
            .autoDarkModeEnable(true, 0.2f)
    }


//---------------------------------------other---------------------------------------
    /**
     * 初始化软键盘
     */
    protected open fun initSoftKeyboard() {
        // 点击外部隐藏软键盘，提升用户体验
        getContentView()?.setOnClickListener {
            // 隐藏软键，避免内存泄漏
            hideKeyboard(currentFocus)
        }
    }

    override fun getBundle(): Bundle? {
        return intent.extras
    }

    override fun startActivity(intent: Intent) {
        return super<AppCompatActivity>.startActivity(intent)
    }

    override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
        val fragments: MutableList<Fragment?> = supportFragmentManager.fragments
        for (fragment: Fragment? in fragments) {
            // 这个 Fragment 必须是 BaseFragment 的子类，并且处于可见状态
            if (fragment !is BaseFragment<*,*> || fragment.getLifecycle().currentState != Lifecycle.State.RESUMED) {
                continue
            }
            // 将按键事件派发给 Fragment 进行处理
            if (fragment.dispatchKeyEvent(event)) {
                // 如果 Fragment 拦截了这个事件，那么就不交给 Activity 处理
                return true
            }
        }
        return super.dispatchKeyEvent(event)
    }

}